﻿using System;
using System.Data.SqlClient;
using System.IO;
using System.Text;
using System.Diagnostics;

namespace sosql
{
    class Program
    {
        const string prompt = "{0}> ";
        static bool isRunning = true;
        static int lineNo = 1;
        static int columnWidth = 10;
        static SqlConnection sqlConn;
        static StringBuilder sql = new StringBuilder();
        static int lineCount = 0;

        static void Main(string[] args)
        {
            Parameters param = new Parameters(args);
            sqlConn = new SqlConnection(param.ConnectionString);
            sqlConn.FireInfoMessageEventOnUserErrors = true;
            sqlConn.InfoMessage += new SqlInfoMessageEventHandler(sqlConn_InfoMessage);
            try
            {
                sqlConn.Open();
            }
            catch (SqlException sqex)
            {
                Console.WriteLine(sqex.Message);
                Environment.Exit(1);
            }

            if (param.SetQuotedIdentifier)
            {
                ProcessLine("SET QUOTED_IDENTIFIER ON");
                ProcessLine("GO");
            }

            string line = string.Empty;
            if (param.HasInput)
            {
                StringReader sr = new StringReader(param.InputData);
                while (sr.Peek() > -1)
                {
                    if(!param.SuppressNumbering)
                        Console.Write(String.Format(prompt, lineNo));
                    line = sr.ReadLine();
                    if(param.EchoInput)
                        Console.WriteLine(line);
                    ProcessLine(line);
                    lineCount++;
                }
                sqlConn.Close();
            }
            else // normal cmd line behaviour
            {
                while (isRunning)
                {
                    if (!param.SuppressNumbering)
                        Console.Write(String.Format(prompt, lineNo));
                    line = Console.ReadLine();
                    ProcessLine(line);
                }
            }
        }

        static void sqlConn_InfoMessage(object sender, SqlInfoMessageEventArgs e)
        {
            Console.WriteLine(e.Message);
        }

        static void ProcessLine(string line)
        {
            switch (line.ToLower().Trim())
            {
                case "go":
                    if (sql.ToString().Trim().Length > 0)
                    {
                        SqlCommand sqlCmd = new SqlCommand(sql.ToString(), sqlConn);
                        SqlDataReader dr = sqlCmd.ExecuteReader();
                        if (dr.HasRows)
                        {
                            bool dumpColumns = false;
                            while (dr.Read())
                            {
                                if (!dumpColumns)
                                {
                                    for (int rowLoop = 0; rowLoop < dr.FieldCount; rowLoop++)
                                    {
                                        Console.Write(dr.GetName(rowLoop).PadRight(columnWidth).Substring(0, columnWidth));
                                    }
                                    Console.WriteLine();
                                    dumpColumns = true;
                                }
                                for (int rowLoop = 0; rowLoop < dr.FieldCount; rowLoop++)
                                {
                                    Console.Write(dr[rowLoop].ToString().PadRight(columnWidth).Substring(0, columnWidth));
                                }
                                Console.WriteLine();
                            }
                        }
                        dr.Close();
                    }
                    lineNo = 1;
                    sql.Length = 0;
                    break;
                case "exit":
                    sqlConn.Close();
                    isRunning = false;
                    break;
                default:
                    sql.Append(line);
                    sql.Append(Environment.NewLine);
                    lineNo++;
                    break;
            }
        }
    }
}
